/*
 * Copyright (C) 2011  John Lawrence thegordo.john at gmail.com
 * Licensed under GPLv3 or later. see http://www.gnu.org/copyleft/gpl.html
 */

package org.jklawrencefam.server.smtp.command;

import org.jklawrencefam.annotation.smtp.SmtpCommandProcessor;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.*;

/**
 * User: John Lawrence
 * Date: 5/24/11
 * Time: 6:20 AM
 */
public class SmtpCommandFactory {


    private static List<String> validCommands = new ArrayList<String>();
    private static Map<String, Class> classMap = new HashMap<String, Class>();

    static {
        Properties classHash = new Properties();
        try {
            InputStream stream = SmtpCommandFactory.class.getClassLoader().getResourceAsStream(SmtpCommandProcessor.PROPERTY_FILENAME);
            classHash.load(stream);
            for (String name : classHash.stringPropertyNames()) {
                classMap.put(name, Class.forName(classHash.getProperty(name)));
                validCommands.add(name);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // Commands that are known but not supported
        validCommands.add("EXPN");
        validCommands.add("HELP");
        validCommands.add("SEND");
        validCommands.add("SAML");
        validCommands.add("SOML");
        validCommands.add("TURN");
    }

    public static SmtpCommand getCommand(String desired, String communication) {

        Class commandClass = classMap.get(desired);
        if (commandClass == null) {
            if (validCommands.contains(desired)) {
                return new Unsupported(desired);
            } else {
                return new DoesNotExist();
            }
        }
        try {
            Constructor cons = commandClass.getDeclaredConstructor(String.class);
            return (SmtpCommand) cons.newInstance(communication);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new DoesNotExist();
    }
}
